package com.easy.orm.source;

import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;

import javax.sql.DataSource;

/**
 * 数据连接池
 * 
 * @author kun
 *
 */
public class EasyDataSource implements DataSource {

	/**
	 * 日志输出
	 */
	private Logger logger = Logger.getLogger(EasyDataSource.class.getName());

	/**
	 * 持有数据库连接
	 */
	private LinkedList<Connection> connections = new LinkedList<>();

	/**
	 * 最大连接数
	 */
	private int maxSize = 5;

	/**
	 * 驱动名称
	 */
	private String driver;

	/**
	 * url
	 */
	private String url;

	/**
	 * 用户名
	 */
	private String username;

	/**
	 * 密码
	 */
	private String password;

	/**
	 * 实例化
	 */
	public EasyDataSource() {
		super();
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see javax.sql.CommonDataSource#getParentLogger()
	 */
	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		return logger;
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see java.sql.Wrapper#isWrapperFor(java.lang.Class)
	 */
	@Override
	public boolean isWrapperFor(Class<?> arg0) throws SQLException {
		return false;
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see java.sql.Wrapper#unwrap(java.lang.Class)
	 */
	@Override
	public <T> T unwrap(Class<T> arg0) throws SQLException {
		return null;
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see javax.sql.DataSource#getConnection()
	 */
	@Override
	public Connection getConnection() throws SQLException {
		return getConnection(username, password);
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String)
	 */
	@Override
	public Connection getConnection(String username, String password) throws SQLException {
		Connection connection = null;
		if (connections.size() > 0) {
			connection = connections.getFirst();
			connections.removeFirst();
		} else {
			connection = createConnection(username, password);
		}
		return connection;
	}

	/**
	 * 创建 数据库连接
	 * 
	 * @param username 用户名
	 * @param password 密码
	 * @return 数据库连接
	 * @throws SQLException 创建失败
	 */
	private Connection createConnection(String username, String password) throws SQLException {
		try {
			Class.forName(driver);
			Connection connection;
			if (username == null || password == null) {
				connection = DriverManager.getConnection(url);
			} else {
				connection = DriverManager.getConnection(url, username, password);
			}
			Connection proxy = (Connection) Proxy.newProxyInstance(EasyDataSource.class.getClassLoader(),
					connection.getClass().getInterfaces(), new InvocationHandler() {

						/**
						 * 关闭方法名称
						 */
						private static final String CLOSE_METHOD_NAME = "close";

						/**
						 * 代理方法
						 * 
						 * @param obj 代理对象
						 * @param m 方法
						 * @param arg 参数
						 * @return 代理方法返回结果
						 * @throws Throwable 代理异常
						 */
						public Object invoke(Object obj, Method m, Object[] arg) throws Throwable {
							if (CLOSE_METHOD_NAME.equals(m.getName()) && connections.size() < maxSize) {
								// 加到池中供其他线程訪问
								connections.addLast((Connection) obj);
								return null;
							}
							return m.invoke(connection, arg);
						}
					});
			return proxy;
		} catch (ClassNotFoundException e) {
			throw new SQLException(e);
		}
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see javax.sql.DataSource#getLogWriter()
	 */
	@Override
	public PrintWriter getLogWriter() throws SQLException {
		return null;
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see javax.sql.DataSource#getLoginTimeout()
	 */
	@Override
	public int getLoginTimeout() throws SQLException {
		return 0;
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see javax.sql.DataSource#setLogWriter(java.io.PrintWriter)
	 */
	@Override
	public void setLogWriter(PrintWriter arg0) throws SQLException {

	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see javax.sql.DataSource#setLoginTimeout(int)
	 */
	@Override
	public void setLoginTimeout(int arg0) throws SQLException {

	}

	public String getDriver() {
		return driver;
	}

	public void setDriver(String driver) {
		this.driver = driver;
	}

	/**
	 * 获取url
	 * 
	 * @return url
	 */
	public String getUrl() {
		return url;
	}

	/**
	 * 设置url
	 * 
	 * @param url url
	 */
	public void setUrl(String url) {
		this.url = url;
	}

	/**
	 * 获取用户名
	 * 
	 * @return 用户名称
	 */
	public String getUsername() {
		return username;
	}

	/**
	 * 设置用户名
	 * 
	 * @param username 用户名
	 */
	public void setUsername(String username) {
		this.username = username;
	}

	/**
	 * 获取密码
	 * 
	 * @return 密码
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * 设置密码
	 * 
	 * @param password 密码
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * 获取最大连接数
	 * 
	 * @return 最大持有数据连接
	 */
	public int getMaxSize() {
		return maxSize;
	}

	/**
	 * 设置最大连接数
	 * 
	 * @param maxSize 最大持有数据连接
	 */
	public void setMaxSize(int maxSize) {
		this.maxSize = maxSize;
	}

	/**
	 * 获取连接池 持有连接大小
	 * 
	 * @return size
	 */
	public int getSize() {
		return connections.size();
	}

}
